package fem2;

import java.util.HashSet;
import java.util.Set;

/**
 * abstract class for any class that manage many elements (like material model)
 * 
 * @author hbui
 * 
 */
public abstract class ElementManager {

	/** One single element that is connected for fast access */
	private Element anElement_ = null;

	/**
	 * The set of elements this constitutive model is a part of
	 */
	// private Set<Element> elements_ = new TreeSet<Element>();
	private Set<Element> elements_ = new HashSet<Element>();

	/**
	 * Returns one of the finite elements this object is part of or
	 * <code>null</code> if this object is not part of any element.
	 * 
	 * @return an element.
	 */
	Element getAnElement() {
		return anElement_;
	}

	/**
	 * Returns an array containing all elements this object is a part of.
	 * 
	 * @return an array of elements that refer to this object
	 */
	public Element[] getElements() {
		return elements_.toArray(new Element[elements_.size()]);
	}

	/**
	 * Registers the specified finite element, i.e. this object is now a part of
	 * the specified element. This method is usually invoked when a finite
	 * element is constructed or when a part of a finite element is substituted.
	 * More specialized versions of the class may want to override this method.
	 * 
	 * @param element
	 *            another finite element this object is a part of.
	 * @throws NullPointerException
	 *             if the specified element is <code>null</code>.
	 */
	public void registerElement(Element element) {
		if (element == null) {
			throw new NullPointerException("Can't register null");
		}
		assert !isPartOf(element);

		elements_.add(element);
		anElement_ = element;
	}

	/**
	 * Returns <code>true</code> if this object is part of the specified finite
	 * element.
	 * 
	 * @param element
	 *            finite element
	 * @return <code>true</code> if this object is part of the specified finite
	 *         element.
	 */
	public boolean isPartOf(Element element) {
		return elements_.contains(element);
	}

	/**
	 * Unregisters the specified finite element, i.e. this object is no longer a
	 * part of the specified element. This method is usually invoked when a
	 * finite element is destructed or when a part of a finite element is
	 * substituted. More specialized versions of the class may want to override
	 * this method.
	 * 
	 * @param element
	 *            the finite element this object is no longer a part of.
	 */
	public void unregisterElement(Element element) {
		assert isPartOf(element);

		elements_.remove(element);
		if (element == anElement_) {
			if (elements_.size() > 0) {
				anElement_ = elements_.iterator().next();
			} else {
				anElement_ = null;
			}
		}
	}
}
